from django.db import models
from datetime import datetime, date
from django.contrib.auth.models import User, UserManager

from bookmarks.models import Bookmark
from crm.models import Organisation, Client

from tagging.fields import TagField
from tagging.models import Tag

class Person(User):
  code = models.CharField(max_length=5)
  effort = models.FloatField(default=1)
  """User with app settings."""
  timezone = models.CharField(max_length=50, default='Europe/London')
  objects = UserManager()
  def __unicode__(self):
    return self.code

class Project(models.Model):
  code = models.CharField(max_length=5)
  title = models.CharField(max_length=100)
  description = models.TextField(null = True, blank = True, )
  start_date = models.DateField('start date')
  end_date = models.DateField('end date')
  member = models.ManyToManyField(Person)
  organisation = models.ManyToManyField(Organisation)
  def __unicode__(self):
    return self.title

class WorkPackage(models.Model):
  code = models.CharField(max_length=5)
  title = models.CharField(max_length=100)
  start_date = models.DateField('start date')
  end_date = models.DateField('end date')
  project = models.ForeignKey(Project)
  def __unicode__(self):
    return self.project.code + ":" + self.code + ' ' + self.title

class DeliverableType(models.Model):
  title = models.CharField(max_length=100)
  description = models.TextField()
  def __unicode__(self):
    return self.title

class Aim(models.Model):
  title = models.CharField(max_length=100)
  description= models.TextField()
  work_package = models.ForeignKey(WorkPackage)
  def __unicode__(self):
    return self.title

class TaskManager(models.Manager):
    def incomplete(self):
      return self.filter(completed_date = None)

    def complete(self):
      return self.exclude(completed_date = None)

    def overdue(self):
      return self.filter(completed_date = None, target_date__lt = date.today())

    def dueToday(self):
      return self.filter(completed_date = None, target_date = date.today())

class Task(models.Model):
  title = models.CharField(max_length=100)
  description = models.TextField()
  lead = models.ForeignKey(Person)
  start_date = models.DateField('start date', default=date.today)
  target_date = models.DateField('target date', blank=True, null=True)
  completed_date = models.DateField('completion date', blank=True, null=True)
  parent = models.ForeignKey('self', blank=True, null=True, related_name='subtasks')
  organisation = models.ManyToManyField(Organisation, null=True, blank=True)
  tags = TagField(null=True)
  estimate = models.IntegerField('time estimate (minutes)', blank=True, null=True)
  def __unicode__(self):
    return self.title  

  def is_overdue(self):
    if self.target_date < date.today()  and not self.completed_date:
      return True
    else:
      return False

  objects = TaskManager()

class Objective(models.Model):
  title = models.CharField(max_length=100)
  description= models.TextField()
  lead = models.ForeignKey(Person)
  deliverableType = models.ForeignKey(DeliverableType)
  quantity = models.IntegerField()
  start_date = models.DateField('start date', default=date.today)
  target_date = models.DateField('target date')
  aim = models.ForeignKey(Aim)
  task = models.ManyToManyField(Task, null=True, blank=True)
  organisation = models.ManyToManyField(Organisation, null=True, blank=True)
  def __unicode__(self):
    return self.title
  
  def status(self):
    return 'Completed ' + str(self.delivered()) + ' of ' + str(self.quantity) 

  def delivered(self):
    delivered = self.deliverable_set.filter(completed_date__lte = date.today())
    if delivered == False:
      completed = 0
    else:
      completed  = delivered.count()
    return completed

  def overdueDeliverables(self):
    overdue = self.deliverable_set.filter(completed_date = None).filter(target_date__lt = datetime.today())
    return overdue

  def nextDeliverable(self):
    deliverables = self.deliverable_set.filter(start_date__lte = date.today()).filter(completed_date = None).order_by('target_date')
    if deliverables:
      return deliverables[0]
    else:
      return None

  def expected_deliverables_to_date(self):
    total_duration = self.target_date - self.start_date
    expected_velocity = float(float(self.quantity) / total_duration.days)
    expired_duration = date.today()  - self.start_date
    expected_deliverables = (expired_duration.days)  * expected_velocity
    if expected_deliverables < 0:
	  expected_deliverables = 0
    if expected_deliverables > self.quantity:
      expected_deliverables = self.quantity
    return round(expected_deliverables, 1)

  def is_behind_schedule(self):
    expected_deliverables = self.expected_deliverables_to_date()
    return self.delivered() < (expected_deliverables // 1)

  def status(self):
    '''
    Returns a number between -100 and 100 indicating the current status of this
    objective. The more behind schedule the objective is the nearer to -100
    we get, the more ahead of schedule the nearer to +100 we go. 0 is perfectly
    on schedule.
    '''
    status = 0 
    expected_deliverables = self.expected_deliverables_to_date()
    if expected_deliverables > 0 and expected_deliverables > 1:
      status = ((self.delivered() - expected_deliverables) / expected_deliverables) * 100
    elif expected_deliverables > 0:
      status = ((self.delivered() - expected_deliverables) / expected_deliverables) * 10
    return status

  def is_ahead_of_schedule(self):
    return self.delivered() > self.expected_deliverables_to_date()

class DeliverableManager(models.Manager):
    def incomplete(self):
      return self.filter(completed_date = None)

    def overdue(self):
      return self.filter(completed_date = None, target_date__lt = date.today())

    def dueToday(self):
      return self.filter(completed_date = None, target_date = date.today())

class Deliverable(models.Model):
  title = models.CharField(max_length=100)
  description= models.TextField()
  owner = models.ForeignKey(Person)
  start_date = models.DateField('start date', default=date.today)
  target_date = models.DateField('target date')
  estimate = models.IntegerField('time estimate (minutes)', blank=True, null=True)
  completed_date = models.DateField('completed date', null = True, blank=True )
  type = models.ForeignKey(DeliverableType)
  objective = models.ForeignKey(Objective)
  resource = models.ManyToManyField(Bookmark, null=True, blank=True)
  organisation = models.ManyToManyField(Organisation, null=True, blank=True)
  task = models.ManyToManyField(Task, null=True, blank=True)
  tags = TagField(null=True)
  def __unicode__(self):
    return self.title

  def is_overdue(self):
    if self.target_date < date.today()  and not self.completed_date:
      return True
    else:
      return False
  
  def has_bad_estimate(self):
    if self.estimate == None:
      estimate = 0
    else:
      estimate = self.estimate
      
    task_estimate = 0
    for t in Task.objects.filter(deliverable = self.id):
        if t.estimate != None:
          task_estimate = task_estimate + t.estimate
    
    if estimate < task_estimate:
      return True
    else:
      return False
    
  objects = DeliverableManager()










